package com.qingzhuge.member.utils;

import com.qingzhuge.entity.BaseBriefnessEntity;
import com.qingzhuge.entity.FindObjUserCreateBy;
import com.qingzhuge.member.entity.SysImageText;
import com.qingzhuge.member.enums.EnumPublishType;
import com.qingzhuge.member.enums.EnumRoleType;
import com.qingzhuge.utils.PageUtil;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Description: 图文 分页查询
 * @Auther: ChenQ
 * @Date: 2019/1/16 17:35
 */
public class QueryHelp {
    private static final Logger log = LoggerFactory.getLogger(QueryHelp.class);

    public static PageUtil<SysImageText> pageOf(Page<SysImageText> pageList) {
        long totalElements = pageList.getTotalElements();
        if (totalElements > 2147483647L) {
            log.warn("page total max:{}", totalElements);
        }
        return PageUtil.of((int) totalElements, pageList.getSize(), pageList.getNumber() + 1, pageList.getTotalPages(), pageList.isFirst(), pageList.isLast(), pageList.getContent());
    }

    public static Specification<SysImageText> setQueryPageForSpecification(SysImageText entity, boolean isType) {
        return new Specification<SysImageText>() {
            private static final long serialVersionUID = -8724689778806435095L;

            /**
             * @param root  用于获取属性字段
             * @param query 以用于简单条件查询
             * @param cb    用于构造复杂条件查询
             * @return
             */
            @Override
            public Predicate toPredicate(@NotNull Root root, @NotNull CriteriaQuery query, @NotNull CriteriaBuilder cb) {
                //集合 用于封装查询条件
                List<Predicate> list = new ArrayList<>();
                Predicate or = null;
                if (entity != null) {
                    if (StringUtils.isNotBlank(entity.getName())) {
                        //全部模糊查询，即%{address}%
                        log.debug("模糊查询 name:{}", entity.getName());
                        String fieldName = BaseBriefnessEntity.FIELD_NAME;
                        Expression path = root.get(fieldName).as(String.class);
                        Predicate p1 = cb.like(
                                path,
                                "%" + entity.getName() + "%");
                        list.add(p1);
                    }

                    if (entity instanceof FindObjUserCreateBy) {
                        Long createBy = ((FindObjUserCreateBy) entity).getCreateBy();
                        if (null != createBy) {
                            Predicate p3 = cb.equal(root.get("createBy").as(Long.class), createBy);
                            list.add(p3);
                        }
                    }
                    if (StringUtils.isNotBlank(entity.getSearchField())) {
                        boolean existField = isExistField(entity.getClass(), entity.getSearchField());
                        if (existField) {
                            BeanWrapper srcBean = new BeanWrapperImpl(entity);
                            PropertyDescriptor pds = srcBean.getPropertyDescriptor(entity.getSearchField());
                            String pName = pds.getName();
                            Expression expression = root.get(entity.getSearchField()).as(String.class);
                            Object value = srcBean.getPropertyValue(pName);
                            if (null != value && StringUtils.isNotBlank(value.toString())) {
                                Predicate p3 = cb.like(expression, "%" + value + "%");
                                list.add(p3);
                            }
                        } else {
                            BeanWrapper srcBean = new BeanWrapperImpl(entity);
                            PropertyDescriptor pds = srcBean.getPropertyDescriptor(entity.getSearchField());
                            String pName = pds.getName();
                            Class<?> propertyType = pds.getPropertyType();
                            Object value = srcBean.getPropertyValue(pName);
                            if (null != value) {
                                Predicate p3 = cb.equal(root.get(entity.getSearchField()).as(propertyType), value);
                                list.add(p3);
                            }
                        }
                    }
                    Expression expression = root.get("deleted").as(Integer.class);
                    Predicate predicate = cb.equal(expression, SysImageText.DELETE_NORMEL);
                    list.add(predicate);

                    if (entity.getRoleCategory() != null) {
                        Expression roleCategory = root.get("roleCategory").as(EnumRoleType.class);
                        Predicate category = cb.equal(roleCategory, entity.getRoleCategory());
                        list.add(category);
                    }
                    List<Predicate> listType = new ArrayList<>();
                    if (isType) {
                        Expression expressionType = root.get("showCategory").as(EnumPublishType.class);
                        List<EnumPublishType> types = entity.getTypes();
                        if (null != types && !types.isEmpty()) {
                            types.forEach(type -> {
                                Predicate predicates = cb.equal(expressionType, type);
                                listType.add(predicates);
                            });
                            or = cb.or(listType.toArray(new Predicate[0]));
                        }
                    }
                }
                Predicate and = cb.and(list.toArray(new Predicate[0]));
                if (null == or) {
                    return and;
                }
                return cb.and(and, or);
            }
        };
    }

    public static boolean isExistField(Class<?> clazz, String filed) {
        boolean isField;
        for (isField = false; clazz != Object.class; clazz = clazz.getSuperclass()) {
            Field fieldName = null;
            try {
                fieldName = clazz.getDeclaredField(filed);
            } catch (NoSuchFieldException var6) {
                log.debug("entity name:{},filed name:{} is not", clazz.getSimpleName(), filed);
            }
            if (null != fieldName && Objects.equals(fieldName.getName(), filed)) {
                if (Objects.equals(fieldName.getType().getSimpleName(), "String")) {
                    isField = true;
                }
                break;
            }
        }
        return isField;
    }
}
